package db

import (
	"fmt"
	"github.com/google/uuid"
	"github.com/jinzhu/gorm"
	"sola/common"
	"strings"
	"time"
)

type Article struct {
	common.BaseModel
	ArticleId          string `json:"article_id" uri:"article_id" gorm:"size:36;NOT NULL"`
	Title              string `json:"title" gorm:"size:64;NOT NULL"`
	ImageUri           string `json:"image_uri" gorm:"size:256;NOT NULL"`
	ContentShort       string `json:"content_short" gorm:"size:256;NOT NULL"`
	Content            string `json:"content" gorm:"size:102400;NOT NULL"`
	AuthorId           string `json:"author_id" gorm:"size:36"`
	AuthorName         string `json:"author_name" gorm:"size:64"`
	AuthorNickName     string `json:"author_nick_name" gorm:"size:64"`
	UpdateUserId       string `json:"update_user_id" gorm:"size:36"`
	UpdateUserName     string `json:"update_user_name" gorm:"size:64"`
	UpdateUserNickName string `json:"update_user_nick_name" gorm:"size:64"`
	CategoryId         string `json:"category_id" gorm:"size:36"`
	CategoryName       string `json:"category_name" gorm:"size:64"`
	ClassifyId         string `json:"classify_id" gorm:"size:36"`
	ClassifyName       string `json:"classify_name" gorm:"size:64"`
	Importance         uint8  `json:"importance"`
	Status             string `json:"status"`
	TagIds             string `json:"tag_ids" gorm:"size:1024"`
}

func (article *Article) BeforeCreate(scope *gorm.Scope) error {
	return scope.SetColumn("article_id", uuid.New().String())
}

func (carticle *Article) BeforeSave(scope *gorm.Scope) error {
	return scope.SetColumn("updated_at", time.Now())
}

type ArticleScan struct {
	common.BaseModel
	ArticleId      string `json:"article_id"`
	Title          string `json:"title"`
	ImageUri       string `json:"image_uri"`
	ContentShort   string `json:"content_short"`
	AuthorId       string `json:"author_id"`
	AuthorName     string `json:"author_name"`
	AuthorNickName string `json:"author_nick_name"`
	CategoryId     string `json:"category_id"`
	CategoryName   string `json:"category_name"`
	ClassifyId     string `json:"classify_id"`
	ClassifyName   string `json:"classify_name"`
	TagIds         string `json:"tag_ids"`
	Tags           []*Tag `json:"tags"`
	Importance     uint8  `json:"importance"`
	Status         string `json:"status"`
	Readings       string `json:"readings"`
}

func CountArticle(searchModel *common.BaseSearchModel) (count int) {
	searchDB := db.Table("articles")
	if searchModel.UserId != "" {
		searchDB = searchDB.Where("author_id = ?", searchModel.UserId)
	}
	if searchModel.ClassifyId != "" {
		searchDB = searchDB.Where("classify_id = ?", searchModel.ClassifyId)
	}
	if searchModel.CategoryId != "" {
		searchDB = searchDB.Where("category_id = ?", searchModel.CategoryId)
	}
	if searchModel.TagId != "" {
		searchDB = searchDB.Where("tag_ids like ?", "%"+searchModel.TagId+"%")
	}
	searchDB = searchDB.Where("title like ? and status like ? and deleted_at is  NULL", "%"+searchModel.Name+"%", "%"+searchModel.Status+"%")
	searchDB.Count(&count)
	return
}

func GetArticleList(searchModel *common.BaseSearchModel) (scanlist []*ArticleScan) {
	searchDB := db.Table("articles")
	if searchModel.UserId != "" {
		searchDB = searchDB.Where("author_id = ?", searchModel.UserId)
	}
	if searchModel.ClassifyId != "" {
		searchDB = searchDB.Where("classify_id = ?", searchModel.ClassifyId)
	}
	if searchModel.CategoryId != "" {
		searchDB = searchDB.Where("category_id = ?", searchModel.CategoryId)
	}
	searchDB = searchDB.Where("title like ? and status like ?", "%"+searchModel.Name+"%", "%"+searchModel.Status+"%")
	if searchModel.TagId != "" {
		searchDB = searchDB.Where("tag_ids like ?", "%"+searchModel.TagId+"%")
	}
	if searchModel.Limit > 0 {
		searchDB = searchDB.Offset((searchModel.Page - 1) * searchModel.Limit).Limit(searchModel.Limit)
	}
	if searchModel.Sort != "" {
		searchDB = searchDB.Order(searchModel.Sort)
	}
	searchDB.Find(&scanlist)
	for _, article := range scanlist {
		//article.Tags = make([]*Tag, 0)
		tags := make([]*Tag, 0)
		tag_ids := strings.Split(strings.TrimSpace(article.TagIds), ",")
		for _, tag_id := range tag_ids {
			tag_id = strings.TrimSpace(tag_id)
			if len(tag_id) == 0 {
				continue
			}
			var tag Tag
			tag.TagId = tag_id
			db.Where("tag_id = ?", tag.TagId).First(&tag)
			if tag.Id > 0 {
				tags = append(tags, &tag)
			}
		}
		article.Tags = tags
	}
	return
}

func DetailArticle(article *Article) {
	db.Where("id = ?", article.Id).First(article)
	return
}

func ListArticles() (scanlist []*ArticleScan) {
	//var alist []ArticleScan
	db.Table("articles").Scan(&scanlist)
	for _, article := range scanlist {
		article.Tags = make([]*Tag, 0)
		tag_ids := strings.Split(strings.TrimSpace(article.TagIds), ",")
		for _, tag_id := range tag_ids {
			tag_id = strings.TrimSpace(tag_id)
			if len(tag_id) == 0 {
				continue
			}
			var tag Tag
			tag.TagId = tag_id
			db.Where("tag_id = ?", tag.TagId).First(&tag)
			if tag.Id > 0 {
				article.Tags = append(article.Tags, &tag)
			}
		}
	}
	return
}

func FindByArticleId(article_id string) (article *Article, err error) {
	var article_db Article
	article_db.AuthorId = article_id
	db.Where("article_id = ?", article_id).First(&article_db)
	if article_db.Id <= 0 {
		err = fmt.Errorf("article:%s is not found", article_id)
		return
	}
	article = &article_db
	return
}
